#ifndef _SOCK_POOL_H_
#define _SOCK_POOL_H_

//#include <netdb.h>
#include "list_module.h"
#include <time.h>


#define SOCK_MAX_NUM		16 // 16

#define SO_UNX_MAX_NUM		2 // 16
#define SO_TCP_MAX_NUM		8 // 32
#define SO_UDP_MAX_NUM		1
#define SER_PT_MAX_NUM		1
#define FD_POOLMAX_NUM		16 // 1024

#if FD_POOLMAX_NUM < (SO_UNX_MAX_NUM + SO_TCP_MAX_NUM + SO_UDP_MAX_NUM + SER_PT_MAX_NUM)
	#error "FD_POOLMAX_NUM must be larger than (SO_UNX_MAX_NUM + SO_TCP_MAX_NUM + SO_UDP_MAX_NUM + SER_PT_MAX_NUM)"
#endif

/*
 *
 */
typedef unsigned char *		(* sock_deal_packed)( int ind, unsigned char * pbuf, unsigned short len, int be_whole );


/*
 * fdi list
 */
typedef struct
{
	int						fd;
	unsigned int			addr;
	int						port;
	time_t					timer;
}	fd_info_t;

class fdi_list
{
public:
	fdi_list( int max );
	~fdi_list( void )		{ }

	int						insert	( fd_info_t * fdi );
	void					remove	( int fd );
	int						get		( int ind, fd_info_t * fdi );
	void					tick	( void );

	void					show	( void );

public:
	const int				m_max;
	int						m_num;
	array_obj<fd_info_t>	m_lst;
};


/*
 * fd table
 */
#define FD_BUF_SIZE			4096

typedef struct
{
	int						fd;

	int						len;	// rx frame length
	unsigned char *			prx;	// rx frame
}	fd_tabl_t;

class fd_table
{
public:
	fd_table( void );
	~fd_table( void )		{ }

/***********************************************************
	insert a node into socket client table
	has_buf	 1, has a buffer
	 		 0, has no buffer
	return	 0, success
			-1, the fd is out of the table
			-2, the fd is same with a node
			-3, malloc failed
***********************************************************/
	int						insert	( int fd, int has_buf );
	void					remove	( int fd );

	unsigned char *			get		( int fd );

public:
	fd_tabl_t				m_lst[FD_POOLMAX_NUM];
	int						m_num;
};


/*
 * sock pool
 */
class sock_pool
{
public:
	static sock_pool *		instance			( int max = SOCK_MAX_NUM );
	void					free				( void );

	void					re_create			( void );
	void 					so_delete 			( void );

	void					tick				( sock_deal_packed func = NULL );
	int						fd_send				( int ind, unsigned char * pdata, int len );

private:
	//sock_pool();
	sock_pool( int max );
	~sock_pool( void );

	void					create_svr			( void );

	// fd
	void					fd_init				( void );
	void					fd_close			( int fd );
	void					fd_rx_stream		( int fd );
	void					fd_rx_dgram			( int fd );

	// socket
	int						so_server_create	( int type, const struct sockaddr * addr, socklen_t alen, int clt_num );
	int						so_accept_unx		( int svr_fd, char * pcltname );
	int						so_accept_tcp		( int svr_fd );

private:
	static sock_pool *		m_pthis;
	const int				m_max;

	fd_table *				m_tbl;
	fdi_list *				m_fdi;
};

#endif
